﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Web;
using System.IO;
using System.Drawing.Imaging;
using log4net;
using System.Drawing.Drawing2D;
using BetterImageProcessorQuantization;

namespace eShop.Utility
{
    public class ImageResizer
    {
        
        public static string CheckImageMissing(string imageUrl, string noImagePath)
        {
            FileInfo imageFile = new FileInfo(HttpContext.Current.Server.MapPath(imageUrl));
            if (imageFile.Exists)
            {
                //System.Drawing.Size originalImageDimension = ImageResizer.GetImageDimension(imageUrl);
                return imageUrl;
            }
            else
            {
                return noImagePath;
            }
        }

        public static string CreateThumbnail(string parentImageFilePath, string outputImageFilePath, int width, int height, bool addSufix, string sufix)
        {
            // Trying to locate the original image file
            string parentImageFileFullPath = HttpContext.Current.Server.MapPath(parentImageFilePath);

            if (File.Exists(parentImageFileFullPath))
            {
                if (string.IsNullOrEmpty(sufix))
                    sufix = "_thumb";

                // Adding the sufix to the filename
                if (addSufix)
                    outputImageFilePath = (outputImageFilePath.Insert(outputImageFilePath.IndexOf('.'), sufix));

                // Deleting if the file already exists.
                if (File.Exists(outputImageFilePath))
                    FileAccessUtility.DeleteFile(outputImageFilePath);

                // Loading the image from image file
                using (Image parentImage = Image.FromFile(parentImageFileFullPath))
                {
                    // Creating the thumbnail for optimization
                    Image thumbnail = new Bitmap(width, height);
                    Graphics graphic = Graphics.FromImage(thumbnail);

                    graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    graphic.SmoothingMode = SmoothingMode.HighQuality;
                    graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    graphic.CompositingQuality = CompositingQuality.HighQuality;

                    graphic.DrawImage(parentImage, 0, 0, width, height);

                    if (parentImageFilePath.ToLower().EndsWith(".gif"))
                    {
                        using (thumbnail)
                        {
                            OctreeQuantizer quantizer = new OctreeQuantizer(255, 8);
                            using (Bitmap quantized = quantizer.Quantize(thumbnail))
                            {
                                using (FileStream outputStream = new FileStream(HttpContext.Current.Server.MapPath(outputImageFilePath), FileMode.Create))
                                {
                                    quantized.Save(outputStream, ImageFormat.Gif);
                                }
                            }
                        }
                    }
                    else if (parentImageFilePath.ToLower().EndsWith(".jpg"))
                    {
                        ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
                        EncoderParameters encoderParameters;
                        encoderParameters = new EncoderParameters(1);
                        encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
                        using (FileStream outputStream = new FileStream(HttpContext.Current.Server.MapPath(outputImageFilePath), FileMode.Create))
                        {
                            thumbnail.Save(outputStream, info[1], encoderParameters);
                        }
                    }
                    else
                    {
                        Image thumbnailImage = parentImage.GetThumbnailImage(width, height, null, IntPtr.Zero);
                        thumbnailImage.Save(HttpContext.Current.Server.MapPath(outputImageFilePath), parentImage.RawFormat);
                    }
                    return outputImageFilePath;
                }
            }
            else
                return null;
        }

        /// <summary>
        /// Creates a thumbnail image from another image with the width 
        /// specified. Helpful in case of creating a different sized thumbnail 
        /// image from the original image. This method overwrites if the file
        /// already exists.
        /// </summary>
        /// <param name="parentImageFilePath">Path of the original image. This is relative path from site root</param>
        /// <param name="outputImageFilePath">Path of the output image where to create the thumbnail. This includes the output filename.</param>
        /// <param name="width">Desired width of the thumbnail image</param>
        /// <param name="addSufix">If true, an extension is added to differentiate from the original image</param>
        /// <param name="sufix">The sufix to be be added in output filename, if not supplied, _thumb will be used.</param>
        /// <returns>True if the thumbnail is successfuly created, false otherwise</returns>
        public static string CreateThumbnail(string parentImageFilePath, string outputImageFilePath, int width, bool addSufix, string sufix)
        {
            // Trying to locate the original image file
            string parentImageFileFullPath = HttpContext.Current.Server.MapPath(parentImageFilePath);

            if (File.Exists(parentImageFileFullPath))
            {
                if (string.IsNullOrEmpty(sufix))
                    sufix = "_thumb";

                // Adding the sufix to the filename
                if (addSufix)
                    outputImageFilePath = outputImageFilePath.Insert(outputImageFilePath.IndexOf('.'), sufix);

                // Deleting if the file already exists.
                if (File.Exists(outputImageFilePath))
                    FileAccessUtility.DeleteFile(outputImageFilePath);

                // Loading the image from image file
                using (Image parentImage = Image.FromFile(parentImageFileFullPath))
                {
                    
                    int height = (int)(parentImage.Height * ((double)width / (double)parentImage.Width));
                    Image thumbnail = new Bitmap(width, height);
                    Graphics graphic = Graphics.FromImage(thumbnail);

                    graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    graphic.SmoothingMode = SmoothingMode.HighQuality;
                    graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    graphic.CompositingQuality = CompositingQuality.HighQuality;

                    graphic.DrawImage(parentImage, 0, 0, width, height);

                    if (parentImageFilePath.ToLower().EndsWith(".gif"))
                    {
                        using (thumbnail)
                        {
                            OctreeQuantizer quantizer = new OctreeQuantizer(255, 8);
                            using (Bitmap quantized = quantizer.Quantize(thumbnail))
                            {
                                using (FileStream outputStream = new FileStream(HttpContext.Current.Server.MapPath(outputImageFilePath), FileMode.Create))
                                {
                                    quantized.Save(outputStream, ImageFormat.Gif);
                                }
                            }
                        }
                    }
                    else if (parentImageFilePath.ToLower().EndsWith(".jpg"))
                    {
                        ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
                        EncoderParameters encoderParameters;
                        encoderParameters = new EncoderParameters(1);
                        encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
                        using (FileStream outputStream = new FileStream(HttpContext.Current.Server.MapPath(outputImageFilePath), FileMode.Create))
                        {
                            thumbnail.Save(outputStream, info[1], encoderParameters);
                        }
                    }
                    else
                    {
                        // Dynamically calculating the height of the thumbnail image according to ratio
                        Image thumbnailImage = parentImage.GetThumbnailImage(width, height, null, IntPtr.Zero);
                        thumbnailImage.Save(HttpContext.Current.Server.MapPath(outputImageFilePath), parentImage.RawFormat);
                    }
                    return outputImageFilePath;
                }
            }
            else
                return null;
        }

        
        //public static string CreateThumbnail(string parentImageFilePath, string outputImageFilePath, int width, bool addSufix, string sufix,string imageType )
        //{
            
        //    // Trying to locate the original image file
        //    string parentImageFileFullPath = HttpContext.Current.Server.MapPath(parentImageFilePath);

        //    if (File.Exists(parentImageFileFullPath))
        //    {
        //        if (string.IsNullOrEmpty(sufix))
        //            sufix = "_thumb";

        //        // Adding the sufix to the filename
        //        if (addSufix)
        //            outputImageFilePath = outputImageFilePath.Insert(outputImageFilePath.IndexOf('.'), sufix);

        //        // Deleting if the file already exists.
        //        if (File.Exists(outputImageFilePath))
        //            FileAccessUtility.DeleteFile(outputImageFilePath);

        //        // Loading the image from image file
        //        using (Image parentImage = Image.FromFile(parentImageFileFullPath))
        //        {
        //            int height=0;
        //            //if (imageType == ImageResizer.SMALL_THUMB) 
        //            //{
        //            //    height = _smallThumbImageHeight;
        //            //}
        //            //if (imageType == ImageResizer.LARGE_THUMB)
        //            //{
        //            //    height = _largeThumbImageHeight;
        //            //}
        //            //if (imageType == ImageResizer.DETAIL)
        //            //{
        //            //    height = _detailImageHeight;
        //            //}
        //            //if (imageType == ImageResizer.LIST)
        //            //{
        //            //    height = _listImageHeight;
        //            //}
        //            //if (imageType == ImageResizer.MAX)
        //            //{
        //            //    height = _maxImageHeight;
        //            //}
        //            //if (imageType == ImageResizer.ORIGINAL)
        //            //{
        //            //    height = parentImage.Height;
        //            //}
                    
        //            //int height = (int)(parentImage.Height * ((double)width / (double)parentImage.Width));

        //            // Creating the thumbnail and saving it 
        //            Image thumbnail = new Bitmap(width, height);
        //            Graphics graphic = Graphics.FromImage(thumbnail);

        //            graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
        //            graphic.SmoothingMode = SmoothingMode.HighQuality;
        //            graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
        //            graphic.CompositingQuality = CompositingQuality.HighQuality;

        //            graphic.DrawImage(parentImage, 0, 0, width, height);

        //            if (parentImageFilePath.ToLower().EndsWith(".gif"))
        //            {
        //                using (thumbnail)
        //                {
        //                    OctreeQuantizer quantizer = new OctreeQuantizer(255, 8);
        //                    using (Bitmap quantized = quantizer.Quantize(thumbnail))
        //                    {
        //                        using (FileStream outputStream = new FileStream(HttpContext.Current.Server.MapPath(outputImageFilePath), FileMode.Create))
        //                        {
        //                            quantized.Save(outputStream, ImageFormat.Gif);
        //                        }
        //                    }
        //                }
        //            }
        //            else if (parentImageFilePath.ToLower().EndsWith(".jpg"))
        //            {
        //                ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
        //                EncoderParameters encoderParameters;
        //                encoderParameters = new EncoderParameters(1);
        //                encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
        //                using (FileStream outputStream = new FileStream(HttpContext.Current.Server.MapPath(outputImageFilePath), FileMode.Create))
        //                {
        //                    thumbnail.Save(outputStream, info[1], encoderParameters);
        //                }
        //            }
        //            else
        //            {
        //                // Dynamically calculating the height of the thumbnail image according to ratio
        //                Image thumbnailImage = parentImage.GetThumbnailImage(width, height, null, IntPtr.Zero);
        //                thumbnailImage.Save(HttpContext.Current.Server.MapPath(outputImageFilePath), parentImage.RawFormat);
        //            }
        //            return outputImageFilePath;
        //        }
        //    }
        //    else
        //        return null;
        //}
        /// <summary>
        /// Creates a thumbnail image from another image with the width and height
        /// specified. Helpful in case of creating a different sized thumbnail 
        /// image from the original image.
        /// </summary>
        /// <param name="parentImageFilePath">Path of the original image. This is relative path from site root</param>
        /// <param name="outputImageFilePath">Path of the output image where to create the thumbnail. This includes the output filename.</param>
        /// <param name="height">Desired height of the thumbnail image</param>
        /// <param name="addSufix">If true, an extension is added to differentiate from the original image</param>
        /// <param name="sufix">The sufix to be be added in output filename, if not supplied, _thumb will be used.</param>
        /// <returns>True if the thumbnail is successfuly created, false otherwise</returns>
        public static string CreateThumbnailByHeight(string parentImageFilePath, string outputImageFilePath, int height, bool addSufix, string sufix)
        {
            // Trying to locate the original image file
            string parentImageFileFullPath = HttpContext.Current.Server.MapPath(parentImageFilePath);

            if (File.Exists(parentImageFileFullPath))
            {
                if (string.IsNullOrEmpty(sufix))
                    sufix = "_thumb";

                // Adding the sufix to the filename
                if (addSufix)
                    outputImageFilePath = outputImageFilePath.Insert(outputImageFilePath.IndexOf('.'), sufix);

                // Deleting if the file already exists.
                if (File.Exists(outputImageFilePath))
                    FileAccessUtility.DeleteFile(outputImageFilePath);

                // Loading the image from image file
                using (Image parentImage = Image.FromFile(parentImageFileFullPath))
                {
                    // Dynamically calculating the width of the thumbnail image according to ratio
                    int width = (int)(parentImage.Width * ((double)height / (double)parentImage.Height));

                    // Creating the thumbnail and saving it 
                    Image thumbnail = new Bitmap(width, height);
                    Graphics graphic = Graphics.FromImage(thumbnail);

                    graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    graphic.SmoothingMode = SmoothingMode.HighQuality;
                    graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    graphic.CompositingQuality = CompositingQuality.HighQuality;

                    graphic.DrawImage(parentImage, 0, 0, width, height);

                    if (parentImageFilePath.ToLower().EndsWith(".gif"))
                    {
                        using (thumbnail)
                        {
                            OctreeQuantizer quantizer = new OctreeQuantizer(255, 8);
                            using (Bitmap quantized = quantizer.Quantize(thumbnail))
                            {
                                using (FileStream outputStream = new FileStream(HttpContext.Current.Server.MapPath(outputImageFilePath), FileMode.Create))
                                {
                                    quantized.Save(outputStream, ImageFormat.Gif);
                                }
                            }
                        }
                    }
                    else if (parentImageFilePath.ToLower().EndsWith(".jpg"))
                    {
                        ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
                        EncoderParameters encoderParameters;
                        encoderParameters = new EncoderParameters(1);
                        encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
                        using (FileStream outputStream = new FileStream(HttpContext.Current.Server.MapPath(outputImageFilePath), FileMode.Create))
                        {
                            thumbnail.Save(outputStream, info[1], encoderParameters);
                        }
                    }
                    else
                    {
                        Image thumbnailImage = parentImage.GetThumbnailImage(width, height, null, IntPtr.Zero);
                        thumbnailImage.Save(HttpContext.Current.Server.MapPath(outputImageFilePath), parentImage.RawFormat);
                    }
                    return outputImageFilePath;
                }
            }
            else
                return null;
        }

        /// <summary>
        /// Rotates and flips an image and saves in the destination folder
        /// </summary>
        /// <param name="parentImageFilePath">Path of the original image. This is relative path from site root</param>
        /// <param name="outputImageFilePath">Path of the output image where to create the thumbnail. This includes the output filename.</param>
        /// <param name="ratioPercent">Ratio in percentage in which to set the width and height of the new image</param>
        /// <param name="angleOrDirection">Angle of rotation, or filp direction</param>
        /// <param name="addSufix">If true, an extension is added to differentiate from the original image</param>
        /// <param name="sufix">The sufix to be be added in output filename, if not supplied, _thumb will be used.</param>
        /// <returns>True if the rotated image is successfuly created, false otherwise</returns>
        public static string RotateOrFlip(string parentImageFilePath, string outputImageFilePath, int ratioPercent,
            RotateFlipType angleOrDirection, bool addSufix, string sufix)
        {
            try
            {
                // Trying to locate the original image file
                FileInfo parentImageFile = new FileInfo(HttpContext.Current.Server.MapPath(parentImageFilePath));
                if (parentImageFile.Exists)
                {
                    if (string.IsNullOrEmpty(sufix))
                        sufix = "_thumb";

                    // Adding the sufix to the filename
                    if (addSufix)
                        outputImageFilePath = outputImageFilePath.Insert(outputImageFilePath.IndexOf('.'), sufix);

                    // Deleting if the file already exists.
                    if (File.Exists(outputImageFilePath))
                        FileAccessUtility.DeleteFile(outputImageFilePath);

                    // Loading the image from image file
                    using (Image parentImage = Image.FromFile(parentImageFile.FullName))
                    {
                        // Calculating the width and height dynamically based
                        // on provided ratio
                        int width = (int)(parentImage.Width * ratioPercent / 100.0);
                        int height = (int)(parentImage.Height * ratioPercent / 100.0);

                        // Creating the thumbnail and saving it 
                        Image thumbnailImage = parentImage.GetThumbnailImage(width, height, null, IntPtr.Zero);
                        thumbnailImage.RotateFlip(angleOrDirection);
                        thumbnailImage.Save(HttpContext.Current.Server.MapPath(outputImageFilePath), parentImage.RawFormat);
                        return outputImageFilePath;
                    }
                }
                else
                    return null;
            }
            catch (Exception ex)
            {
                // Setting log information about the exception
                StringBuilder logText = new StringBuilder("Rotate flip image caused server error: Parameters( ");
                logText = logText.Append("parentImageFilePath -> ").Append(parentImageFilePath);
                logText = logText.Append("outputImageFilePath -> ").Append(outputImageFilePath);
                logText = logText.Append("ratioPercent -> ").Append(ratioPercent.ToString());
                logText = logText.Append("angleOrDirection -> ").Append(angleOrDirection.ToString());
                logText = logText.Append("addSufix -> ").Append(addSufix.ToString());
                logText = logText.Append("sufix -> ").Append(sufix);
                logText = logText.Append(" )");

                // Write the log into handled exception list
                ILog log = LogHelper.GetHandledFileLogger("ImageResizer");
                if (log.IsErrorEnabled)
                    log.Error(logText.ToString(), ex);

                throw ex;
            }
        }

        /// <summary>
        /// Saves the image in specified format. Useful for converting one type of image into other type of image
        /// </summary>
        /// <param name="parentImageFilePath">Path of the original image. This is relative path from site root</param>
        /// <param name="outputImageFilePath">Path of the folder where to create the new image</param>
        /// <param name="outputFormat">Format of the image file</param>
        /// <param name="sufix">user defined sufix to add in the new image</param>
        /// <returns>True if the new image is saved successfuly, false otherwise</returns>
        public static string SaveAs(string parentImageFilePath, string outputImageFilePath, ImageFormat outputFormat)
        {
            try
            {
                // Using a temporary memory buffer to save the image in different format
                using (MemoryStream tempBuffer = new MemoryStream())
                {
                    FileInfo imageFile = new FileInfo(HttpContext.Current.Server.MapPath(parentImageFilePath));
                    if (imageFile.Exists)
                    {
                        // Loading the image from image file
                        using (Bitmap parentImage = new Bitmap(imageFile.FullName))
                        {
                            // Converting the image type and saving in buffer
                            parentImage.Save(tempBuffer, outputFormat);
                            // Writing the buffer into file
                            using (FileStream fileStream = new FileStream(HttpContext.Current.Server.MapPath(outputImageFilePath)
                                , FileMode.Create, FileAccess.Write))
                            {
                                tempBuffer.WriteTo(fileStream);
                                tempBuffer.Close();
                                tempBuffer.Dispose();
                                parentImage.Dispose();
                                return outputImageFilePath;
                            }
                        }
                    }
                    else
                        return null;
                }
            }
            catch (Exception ex)
            {
                // Setting log information about the exception
                StringBuilder logText = new StringBuilder("Image save as caused server error: Parameters( ");
                logText = logText.Append("parentImageFilePath -> ").Append(parentImageFilePath);
                logText = logText.Append("outputImageFilePath -> ").Append(outputImageFilePath);
                logText = logText.Append("outputFormat -> ").Append(outputFormat.ToString());
                logText = logText.Append(" )");

                // Write the log into handled exception list
                ILog log = LogHelper.GetHandledFileLogger("ImageResizer");
                if (log.IsErrorEnabled)
                    log.Error(logText.ToString(), ex);

                throw ex;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="parentImageFilePath">Path of the original image. This is relative path from site root</param>
        /// <param name="outputImageFilePath">Path, where to create the thumbnail</param>
        /// <param name="left">Crop rectangle left pixel distance</param>
        /// <param name="top">Crop rectangle top pixel distance</param>
        /// <param name="width">Crop rectangle width</param>
        /// <param name="height">Crop rectangle height</param>
        /// <param name="addSufix">If true, a _crop extension is added to differentiate from the original image</param>
        /// <returns></returns>
        public static string CreateCrop(string parentImageFilePath, string outputImageFilePath, int left, int top,
            int width, int height)
        {
            try
            {
                // Trying to locate the original image file
                FileInfo imageFile = new FileInfo(HttpContext.Current.Server.MapPath(parentImageFilePath));
                if (imageFile.Exists)
                {
                    // Loading the image from image file
                    using (Image parentImage = Image.FromFile(imageFile.FullName))
                    {
                        // Creating a dummy image with the width and height specified,
                        // 4th parameter should be always IntPtr.Zero
                        Image thumbnailImage = parentImage.GetThumbnailImage(width, height, null, IntPtr.Zero);

                        // Creating the image with the defined rectangle and saving it in file
                        using (Graphics graphics = Graphics.FromImage(thumbnailImage))
                        {
                            graphics.DrawImage(parentImage, new Rectangle(0, 0, width, height), left, top, width,
                                height, GraphicsUnit.Pixel);

                            thumbnailImage.Save(HttpContext.Current.Server.MapPath(outputImageFilePath),
                                parentImage.RawFormat);
                            return outputImageFilePath;
                        }
                    }
                }
                else
                    return null;
            }
            catch (Exception ex)
            {
                // Setting log information about the exception
                StringBuilder logText = new StringBuilder("Image save as caused server error: Parameters( ");
                logText = logText.Append("parentImageFilePath -> ").Append(parentImageFilePath);
                logText = logText.Append("outputImageFilePath -> ").Append(outputImageFilePath);
                logText = logText.Append("left -> ").Append(left.ToString());
                logText = logText.Append("top -> ").Append(top.ToString());
                logText = logText.Append("width -> ").Append(width.ToString());
                logText = logText.Append("height -> ").Append(height.ToString());
                logText = logText.Append(" )");

                // Write the log into handled exception list
                ILog log = LogHelper.GetHandledFileLogger("ImageResizer");
                if (log.IsErrorEnabled)
                    log.Error(logText.ToString(), ex);

                throw ex;
            }
        }

        public static Size GetImageDimension(string imageFilePath)
        {
            Size dimension = new Size();
            // Trying to locate the original image file
            FileInfo imageFile = new FileInfo(HttpContext.Current.Server.MapPath(imageFilePath));
            if (imageFile.Exists)
            {
                // Loading the image from image file
                using (Image image = Image.FromFile(imageFile.FullName))
                {
                    dimension = image.Size;
                }
            }
            return dimension;
        }
    }
}
